package com.sluggard.security.manage.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sluggard.common.exception.BusinessException;
import com.sluggard.security.core.consts.SecurityConstant;
import com.sluggard.security.manage.mapper.RoleMapper;
import com.sluggard.security.manage.mapper.UserMapper;
import com.sluggard.security.manage.model.entity.RoleEntity;
import com.sluggard.security.manage.model.entity.UserEntity;
import com.sluggard.security.manage.model.req.ChangeStatusReq;
import com.sluggard.security.manage.model.req.UserReq;
import com.sluggard.security.manage.model.vo.SecurityUser;
import com.sluggard.security.manage.service.IUserService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户管理 服务实现类
 * </p>
 *
 * @author lizheng
 * @since 2024-04-28
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements IUserService, UserDetailsService {
    @Resource
    private RoleMapper roleMapper;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity userEntity = baseMapper.selectByUsername(username);
        if (Objects.isNull(userEntity)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        if (0 == userEntity.getStatus()) {
            throw new DisabledException("用户被禁用");
        }
        if (Objects.nonNull(userEntity.getExpirationTime()) && LocalDateTime.now().isAfter(userEntity.getExpirationTime())) {
            throw new DisabledException("用户已失效");
        }

        // 获取用户角色信息
        List<RoleEntity> roleEntities = roleMapper.selectRoleByUserId(userEntity.getId());
        if(CollectionUtils.isEmpty(roleEntities)){
            throw new BusinessException("用户未分配角色,无法登录");
        }
        Set<SimpleGrantedAuthority> simpleGrantedAuthorities = roleEntities
                .stream()
                .map(item -> new SimpleGrantedAuthority(SecurityConstant.ROLE_PREFIX + item.getCode())).collect(Collectors.toSet());

        SecurityUser securityUser = new SecurityUser(username, userEntity.getPassword(), simpleGrantedAuthorities);
        BeanUtils.copyProperties(userEntity, securityUser);
        securityUser.setPass(userEntity.getPassword());
        return securityUser;
    }

    @Override
    public void changePassword(UserReq req) {
        UserEntity userEntity = baseMapper.selectByUserId(req.getId());
        if(Objects.isNull(userEntity)){
            throw new BusinessException("数据不存在");
        }
        userEntity.setPassword(passwordEncoder.encode(req.getPassword()));
        baseMapper.updateById(userEntity);
    }

    @Override
    public UserEntity loadEntity(Long id) {
        UserEntity userEntity = baseMapper.selectByUserId(id);
        if(Objects.isNull(userEntity)){
            throw new BusinessException("数据不存在");
        }
        return userEntity;
    }

    @Override
    public void onTables(QueryWrapper<UserEntity> queryWrapper, Page<UserEntity> page) {
        queryWrapper.eq("deleted", 0);
        baseMapper.selectByPage(page, queryWrapper);
    }

    @Override
    public List<UserEntity> onList(QueryWrapper<UserEntity> queryWrapper) {
        queryWrapper.eq("deleted", 0);
        return baseMapper.selectListRelation(queryWrapper);
    }

    @Override
    public void changeRole(SecurityUser userInfo, RoleEntity role) {
        baseMapper.changeRole(userInfo.getId(), role.getId());
    }

    @Override
    public void changeStatus(ChangeStatusReq req) {
        baseMapper.changeStatus(req);
    }


}
